/**
* @file         
* @brief		顺序栈，连续内存块方式.
* @details	    基本功能演示.
* @author		conkty@126.com
* @date		    2023
* @version	    v0.1
* @par 更新记录:         
*	v0.1: 初建\n
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

const unsigned int MAX_SIZE = 3;

typedef struct ElemType {
    int id;
    float value;
} Node;

typedef struct stack_ptrs {
    Node* data;       // 头指针指向栈顶
    Node* top; // 栈顶位置
    Node* bottom; // 栈底位置
} Stack;

void initial(Stack* s) {
    // 预先分配内存
    s->data = NULL; // 预先置0便于后续判断
    s->data = malloc(MAX_SIZE * sizeof(Node));
    if(NULL == s->data) {
        printf("malloc failed! exit!\n");
        exit(-1);
    }

    // 全部内容初始化为空(0)
    memset(s->data, 0, MAX_SIZE * sizeof(Node));
    // 初始化栈顶栈底位置
    s->bottom = s->top = s->data;
}

void destroy(Stack* s) {
    free(s->data);
}

int push(Stack* s, Node* e) {
    assert(NULL != e);

    unsigned int size = s->top - s->bottom;
    if (size >= MAX_SIZE) {
        printf("stack is full, push failed, id is %d .\n", e->id);
        return -1;
    }

    printf("pushing node with id %d ...\n", e->id);

    *(s->top++) = *e;

    return 0;
}

Node* pop(Stack* s) {
    if(s->top == s->bottom) {
        printf("stack is empty, pop faild.\n");
        return NULL;
    }

    Node *e = --s->top;
    printf("node %d is poped.\n", e->id);

    return e;
}

Node* top(Stack* s) {
    if(s->top == s->bottom) {
        printf("stack is empty, pop faild.\n");
        return NULL;
    }

    return s->top-1;
}

void traverse(Stack* s) {
    printf("top %p bottom %p\n", s->top, s->bottom);
    unsigned int size = s->top - s->bottom;
    printf("size %d\n", size);

    Node *ptr = s->bottom;
    while (ptr < s->top) {
        printf("%d ", ptr->id);
        ++ptr;
    }
    printf("\n");
}

void pop_test(Stack* s) {
    Node *e = pop(s);
    if(NULL != e) {
        printf("succeed to pop %d\n", e->id);
    } else {
        printf("faild to pop.\n");
    }
}

void top_test(Stack* s) {
    Node *e = top(s);
    if(NULL != e) {
        printf("succeed to get top %d\n", e->id);
    } else {
        printf("faild to get top.\n");
    }
}

int main()
{
    Stack s;
    initial(&s);
    traverse(&s);

    pop_test(&s);

    Node a0 = {10, 0.0};
    Node a1 = {11, 0.0};
    Node a2 = {12, 0.0};
    Node a3 = {13, 0.0};
    push(&s, &a0);
    push(&s, &a1);
    push(&s, &a2);
    push(&s, &a3);
    traverse(&s);

    pop_test(&s);
    traverse(&s);

    top_test(&s);

    destroy(&s);

    return 0;
}